	% á
	% é
	% í
	% ó
	% ú
	% ñ


\chapter{Prueba} \label{testing}

\begin{flushright}
\textit{Program testing can be a very effective way to show\\
the presence of bugs, but it is hopelessly inadequate\\
for showing their absence.}\\
E. W. Dijkstra
\end{flushright}

\section{Introducción}
 La prueba de software consiste en la verificación \textit{dinámica} del comportamiento de un programa sobre un conjunto \textit{finito} de casos de prueba, apropiadamente seleccionados a partir del dominio de ejecución que usualmente es infinito, en relación con el comportamiento esperado\cite{DBA+ 01}\cite{UL06}. Es una técnica dinámica en el sentido de que el programa se verifica poniéndolo en ejecución de la forma más parecida posible a como se ejecutará cuando este en producción. El programa se prueba ejecutando solo unos pocos casos de prueba dado que por lo general resulta imposible probarlo para todos los valores de entrada posibles, de aquí la frase de Dijkstra.

 En este capítulo se detallan las herramientas utilizadas para dicho fin, junto con algunos ejemplos de las pruebas realizadas y errores encontrados gracias a ellas.
 
\section{Google Test}
 Se utilizo Google Test\footnote{Para más información, visite \url{http://googletest.googlecode.com}} para probar diferentes características o secciones de nuestro proyecto. Dichas pruebas permitieron determinar varias fallas o errores que debieron ser corregidos para lograr un correcto funcionamiento.
 
%\subsection{Conceptos Básicos}
 Al utilizar Google Test se comienza por escribir \textit{aserciones}, las cuales son sentencias que chequean si una determinada condición es verdadera. El resultado de una aserción puede ser exitoso, fallo no fatal o fallo fatal. Si éste último ocurre, la ejecución del test finaliza, de lo contrario la ejecución continúa normalmente.
 
 Los tests utilizan aserciones para verificar el comportamiento del código. Si algún caso de prueba falla o falla alguna aserción, entonces el test falla; de lo contrario el test resulta exitoso.
 
 Un caso de test contiene uno o más tests. Una buena manera de armar casos de tests es agrupar las pruebas dentro de casos de tests que reflejen la estructura del código. Existen situaciones en las cuales se necesita compartir información entre los tests pertenecientes a un caso de test en particular; para estos casos se utilizan un tipo de test denominado \textit{fixture class}. Este tipo de test cuenta con una función de inicialización y/o configuración para cada test, llamada \textit{SetUp()} y una función de finalización, generalmente utilizada para cerrar conexiones con base de datos, destrucción de variables, entre otras, denominada \textit{TearDown()}.

\section{Test Unitarios}
 Actualmente no se cuenta con datos numéricos que muestren el grado de optimización aportado por este trabajo, ya que \aproba forma parte de un proyecto más grande, el cual aún se encuentra en proceso de desarrollo.
 
 Sin embargo, se realizaron distintos tests unitarios que prueban las partes más importantes de \aproba utilizando casos de prueba con información provista por \fudepan.
 
 Para cada paso del algoritmo descripto en la sección \ref{sec:SolucionPropuesta}, se creó una prueba que verifica que su comportamiento es el esperado de acuerdo a los datos de entrada seleccionados. Particularmente, se creó un caso de test del tipo \textit{fixture class} debido a que la salida de un test esta relacionada con la entrada del próximo. De esa forma, se cuenta con ocho test que se corresponden con los pasos de la solución planteada, además de contar con un método \textit{SetUp()} que carga la información de los ARVs y la secuencia nucleotídica, y un método \textit{TearDown()} que se encarga de mostrar la información luego de ser procesada dentro de cada test.
 
 A continuación se muestran algunos de los tests con mayor cantidad de controles y pruebas realizados para éste proyecto.
 
 % SetUp
\subsubsection{SetUp()}
\begin{lstlisting}[language=C++, basicstyle=\footnotesize\ttfamily, keywordstyle=\color{blue}, morekeywords={each, void, in, out}]		
void SetUp()
{
  db.load_file("./ref/AProba/antivirals_AProba_2.xml");
  db.get_antivirals(my_antivirals);
  load_sequence("./ref/AProba/init_seq_AProba.txt", sequence);
  set_default_matrix(_matrix);
}
\end{lstlisting}	
 
 % TearDown
\subsubsection{TearDown()} 
\begin{lstlisting}[language=C++, basicstyle=\footnotesize\ttfamily, keywordstyle=\color{blue}, morekeywords={each, void, in, out}]		
void TearDown()
{
  // If all ASSERTs are OK, the information will be print depending of the stage
  switch (algorithm_step)
  {
    case(1):
      my_antivirals.print_antivirals();
      break;

    case(2):
      my_antivirals.print_all_combinations(arvs_info, false);
      break;

    case(3):
      my_antivirals.print_all_combinations(arvs_info_x, true);
      break;

    case(4):
      my_antivirals.print_expansions(combinations_expanded, false);
      break;

    case(5):
      my_antivirals.print_expansions(combinations_expanded_with_cp, true);
      break;

    case(6):
      my_antivirals.print_combinations_with_genetic_distances(combinations_with_distances, 
                                                                    false);
      break;

    case(7):
      my_antivirals.print_combinations_with_genetic_distances(combinations_with_dist_reduce, 
                                                                    true);
      break;

    case(8):
      my_antivirals.print_all_mutants(mutants_list);
      break;

    default:
      clog << "\n\n End of AProba Algorithm... \n\n" << endl;
      break;
  }
}
\end{lstlisting}	

% Test1 Producto Cartesiano
\subsubsection{Test: Unit\_Test\_calculate\_genetic\_distance}
\begin{lstlisting}[language=C++, basicstyle=\footnotesize\ttfamily, keywordstyle=\color{blue}, morekeywords={each, in, out, TEST\_F,  ASSERT\_LE,  ASSERT\_GE, ASSERT_EQ}]		
TEST_F(FullTest, Unit_Test_calculate_genetic_distance)
{
  // STEP 1
  my_antivirals.pre_processing(sequence);

  // STEP 2 Y 3
  my_antivirals.generate_power_set(arvs_info);

  // STEP 4
  my_antivirals.generate_cartesian_product(arvs_info, arvs_info_x);

  // STEP 5
  my_antivirals.expand_to_nucleotids(sequence, arvs_info_x, combinations_expanded);
  my_antivirals.generate_triplets_cartesian_product(combinations_expanded, 
                                                        combinations_expanded_with_cp);

  // STEP 6
  my_antivirals.calculate_genetic_distance(sequence, _matrix, combinations_expanded_with_cp, 
                                                 combinations_with_distances);



  Combination_Distance_Container::const_iterator it_combinations;
  for (it_combinations = combinations_with_dist_reduce.begin(); 
           it_combinations != combinations_with_dist_reduce.end(); ++it_combinations)
  {
    // All combinations, should have a genetic distance between 3 and 9
    ASSERT_LE(it_combinations->distance, 9);
    ASSERT_GE(it_combinations->distance, 3);
  }

  // This should be the total of combinations after applies calculate genetic distance method
  ASSERT_EQ(combinations_with_distances.size(), 576);
  // This is neccesary to print the correct information
  algorithm_step = 6;
}
\end{lstlisting}	
 
 % Test2 
\subsubsection{Test: Unit\_Test\_generate\_power\_set}
\begin{lstlisting}[language=C++, basicstyle=\footnotesize\ttfamily, keywordstyle=\color{blue}, morekeywords={each, in, out, TEST\_F,  ASSERT\_LE,  ASSERT\_GE, ASSERT_EQ}]		

TEST_F(FullTest, Unit_Test_generate_power_set)
{
   int index_combinations;
   // STEP 1
   my_antivirals.pre_processing(sequence);
   // STEP 2 AND 3
   my_antivirals.generate_power_set(arvs_info);

   ASSERT_NE(my_antivirals.antivirals.size(), 0);

   ResisBasedAntiviral::Combination_Container::const_iterator it_comb_ps;
   index_combinations = 1;
   for (it_comb_ps = arvs_info.begin(); it_comb_ps != arvs_info.end(); ++it_comb_ps)
   {
     ResisBasedAntiviral::Combination::const_iterator it_comb;
     ResisBasedAntiviral::Combination current_comb = (*it_comb_ps);

     for (it_comb = current_comb.begin(); it_comb != current_comb.end(); ++it_comb)
     {
       // Depending on the group from it comes, the list of combinations will be 'x'
       switch (index_combinations)
       {
         // NRTI3
         case(1):
           // The size of the current list of combinations should be 1
           ASSERT_EQ(it_comb->size(), 1);
           break;

         case(2):
           // The size of the current list of combinations should be 1
           ASSERT_EQ(it_comb->size(), 1);
           break;
         
         // NRTI1
         case(3):
           // The size of the current list of combinations should be 2
           ASSERT_EQ(it_comb->size(), 2);
           break;

         case(4):
           // The size of the current list of combinations should be 2
           ASSERT_EQ(it_comb->size(), 2);
           break;
                
         case(5):
           // The size of the current list of combinations should be 2
           ASSERT_EQ(it_comb->size(), 2);
           break;
                
         case(6):
           // The size of the current list of combinations should be 2
           ASSERT_EQ(it_comb->size(), 2);
           break;
        }
        ++index_combinations;
     }
  }

  // This is neccesary to print the correct information
  algorithm_step = 2;
}  
  
\end{lstlisting}	 
  
\subsection{Errores encontrados}
 Entre los errores encontrados gracias al uso de tests, el más destacado fue una falla al momento de realizar el producto cartesiano, que se encuentra dentro del paso 4) del algoritmo, el cual demandó la creación de una nueva función llamada \textit{split\_antivirals()}, detallada en la sección \ref{sec:SolucionPropuesta}, para brindar una solución a este problema.

% Hablar del split_antivirals()